package com.example.airoles.service;

import com.example.airoles.dto.UserProfile;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Service
public class UserProfileService {
    
    private static final Logger logger = LoggerFactory.getLogger(UserProfileService.class);
    
    // In-memory storage for demo purposes
    // In production, this should be replaced with a database
    private final Map<String, UserProfile> userProfiles = new ConcurrentHashMap<>();
    
    public UserProfile createProfile(String userId, String nickname, String email) {
        if (userProfiles.containsKey(userId)) {
            logger.warn("Attempted to create duplicate profile for user: {}", userId);
            return userProfiles.get(userId);
        }
        
        UserProfile profile = new UserProfile(userId, nickname);
        profile.email = email;
        userProfiles.put(userId, profile);
        
        logger.info("Created new user profile for: {}", userId);
        return profile;
    }
    
    public UserProfile getProfile(String userId) {
        return userProfiles.get(userId);
    }
    
    public UserProfile getOrCreateProfile(String userId, String nickname) {
        return userProfiles.computeIfAbsent(userId, id -> {
            logger.info("Creating new profile for user: {}", userId);
            return new UserProfile(id, nickname != null ? nickname : "User_" + id.substring(0, 8));
        });
    }
    
    public UserProfile updateProfile(String userId, UserProfile updatedProfile) {
        UserProfile existingProfile = userProfiles.get(userId);
        if (existingProfile == null) {
            logger.warn("Attempted to update non-existent profile: {}", userId);
            return null;
        }
        
        // Update modifiable fields
        if (updatedProfile.nickname != null) {
            existingProfile.nickname = updatedProfile.nickname;
        }
        if (updatedProfile.email != null) {
            existingProfile.email = updatedProfile.email;
        }
        if (updatedProfile.preferences != null) {
            existingProfile.preferences = updatedProfile.preferences;
        }
        if (updatedProfile.favoriteRoles != null) {
            existingProfile.favoriteRoles = new ArrayList<>(updatedProfile.favoriteRoles);
        }
        if (updatedProfile.customData != null) {
            existingProfile.customData.putAll(updatedProfile.customData);
        }
        
        existingProfile.lastActiveAt = LocalDateTime.now();
        
        logger.debug("Updated profile for user: {}", userId);
        return existingProfile;
    }
    
    public UserProfile.UserPreferences getPreferences(String userId) {
        UserProfile profile = userProfiles.get(userId);
        return profile != null ? profile.preferences : new UserProfile.UserPreferences();
    }
    
    public UserProfile.UserPreferences updatePreferences(String userId, UserProfile.UserPreferences preferences) {
        UserProfile profile = getOrCreateProfile(userId, null);
        profile.preferences = preferences;
        profile.lastActiveAt = LocalDateTime.now();
        
        logger.debug("Updated preferences for user: {}", userId);
        return profile.preferences;
    }
    
    public void updateConversationStats(String userId, String roleId, String skill) {
        UserProfile profile = getOrCreateProfile(userId, null);
        
        profile.stats.incrementConversation();
        if (roleId != null) {
            profile.stats.updateRoleUsage(roleId);
        }
        if (skill != null) {
            profile.stats.updateSkillUsage(skill);
        }
        
        profile.lastActiveAt = LocalDateTime.now();
        
        // Check for achievements
        checkAndAwardAchievements(profile);
    }
    
    public void updateMessageCount(String userId) {
        UserProfile profile = userProfiles.get(userId);
        if (profile != null) {
            profile.stats.incrementMessage();
            profile.lastActiveAt = LocalDateTime.now();
        }
    }
    
    public void addFavoriteRole(String userId, String roleId) {
        UserProfile profile = getOrCreateProfile(userId, null);
        if (!profile.favoriteRoles.contains(roleId)) {
            profile.favoriteRoles.add(roleId);
            logger.debug("Added favorite role {} for user: {}", roleId, userId);
        }
    }
    
    public void removeFavoriteRole(String userId, String roleId) {
        UserProfile profile = userProfiles.get(userId);
        if (profile != null) {
            profile.favoriteRoles.remove(roleId);
            logger.debug("Removed favorite role {} for user: {}", roleId, userId);
        }
    }
    
    public List<String> getFavoriteRoles(String userId) {
        UserProfile profile = userProfiles.get(userId);
        return profile != null ? new ArrayList<>(profile.favoriteRoles) : new ArrayList<>();
    }
    
    public List<UserProfile> getActiveUsers(int limit) {
        return userProfiles.values().stream()
                .sorted((a, b) -> b.lastActiveAt.compareTo(a.lastActiveAt))
                .limit(limit)
                .collect(Collectors.toList());
    }
    
    public Map<String, Object> getUserAnalytics(String userId) {
        UserProfile profile = userProfiles.get(userId);
        if (profile == null) {
            return new HashMap<>();
        }
        
        Map<String, Object> analytics = new HashMap<>();
        analytics.put("totalConversations", profile.stats.totalConversations);
        analytics.put("totalMessages", profile.stats.totalMessages);
        analytics.put("mostUsedRole", profile.stats.mostUsedRole);
        analytics.put("mostUsedSkill", profile.stats.mostUsedSkill);
        analytics.put("roleUsageStats", profile.stats.roleUsage);
        analytics.put("skillUsageStats", profile.stats.skillUsage);
        analytics.put("achievements", profile.stats.achievements);
        analytics.put("streakDays", profile.stats.streakDays);
        analytics.put("memberSince", profile.createdAt);
        analytics.put("lastActive", profile.lastActiveAt);
        
        return analytics;
    }
    
    public List<String> getRecommendationsForUser(String userId) {
        UserProfile profile = userProfiles.get(userId);
        if (profile == null || !profile.preferences.autoRecommendRoles) {
            return new ArrayList<>();
        }
        
        List<String> recommendations = new ArrayList<>();
        
        // Recommend based on interests
        if (profile.preferences.interests.contains("philosophy")) {
            recommendations.add("philosopher");
            recommendations.add("socrates");
        }
        if (profile.preferences.interests.contains("psychology")) {
            recommendations.add("therapist");
            recommendations.add("life_coach");
        }
        if (profile.preferences.interests.contains("literature")) {
            recommendations.add("harry");
        }
        
        // Recommend based on usage patterns
        if (profile.stats.mostUsedRole != null) {
            String mostUsed = profile.stats.mostUsedRole;
            if ("socrates".equals(mostUsed)) {
                recommendations.add("philosopher");
            } else if ("therapist".equals(mostUsed)) {
                recommendations.add("life_coach");
            }
        }
        
        // Remove duplicates and limit
        return recommendations.stream()
                .distinct()
                .limit(3)
                .collect(Collectors.toList());
    }
    
    public boolean deleteProfile(String userId) {
        UserProfile removed = userProfiles.remove(userId);
        if (removed != null) {
            logger.info("Deleted profile for user: {}", userId);
            return true;
        }
        return false;
    }
    
    public long getTotalUsers() {
        return userProfiles.size();
    }
    
    public Map<String, Object> getSystemStats() {
        long totalUsers = userProfiles.size();
        long activeToday = userProfiles.values().stream()
                .filter(p -> p.lastActiveAt.isAfter(LocalDateTime.now().minusDays(1)))
                .count();
        
        int totalConversations = userProfiles.values().stream()
                .mapToInt(p -> p.stats.totalConversations)
                .sum();
        
        Map<String, Object> stats = new HashMap<>();
        stats.put("totalUsers", totalUsers);
        stats.put("activeToday", activeToday);
        stats.put("totalConversations", totalConversations);
        stats.put("averageConversationsPerUser",
                 totalUsers > 0 ? (double) totalConversations / totalUsers : 0);
        
        return stats;
    }
    
    private void checkAndAwardAchievements(UserProfile profile) {
        List<String> achievements = profile.stats.achievements;
        
        // First conversation achievement
        if (profile.stats.totalConversations == 1 && !achievements.contains("first_chat")) {
            achievements.add("first_chat");
            logger.debug("Awarded 'first_chat' achievement to user: {}", profile.userId);
        }
        
        // Conversation milestones
        if (profile.stats.totalConversations >= 10 && !achievements.contains("chat_enthusiast")) {
            achievements.add("chat_enthusiast");
            logger.debug("Awarded 'chat_enthusiast' achievement to user: {}", profile.userId);
        }
        
        if (profile.stats.totalConversations >= 50 && !achievements.contains("conversation_master")) {
            achievements.add("conversation_master");
            logger.debug("Awarded 'conversation_master' achievement to user: {}", profile.userId);
        }
        
        // Role diversity achievement
        if (profile.stats.roleUsage.size() >= 5 && !achievements.contains("role_explorer")) {
            achievements.add("role_explorer");
            logger.debug("Awarded 'role_explorer' achievement to user: {}", profile.userId);
        }
        
        // Skill diversity achievement
        if (profile.stats.skillUsage.size() >= 8 && !achievements.contains("skill_collector")) {
            achievements.add("skill_collector");
            logger.debug("Awarded 'skill_collector' achievement to user: {}", profile.userId);
        }
    }
}